package com.cxyd.modules.wcs.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.cxyd.common.constant.RcsConstants;
import com.cxyd.common.constant.WcsConstants;
import com.cxyd.common.service.impl.CrudServiceImpl;
import com.cxyd.common.utils.ProcResult;
import com.cxyd.modules.wcs.dao.AgvTrkHkDao;
import com.cxyd.modules.wcs.dao.PostWmsDao;
import com.cxyd.modules.wcs.dao.ReceiveTaskDao;
import com.cxyd.modules.wcs.dao.TrkDao;
import com.cxyd.modules.wcs.dto.TrkDTO;
import com.cxyd.modules.wcs.entity.AgvTrkHkEntity;
import com.cxyd.modules.wcs.entity.PostWmsEntity;
import com.cxyd.modules.wcs.entity.ReceiveTaskEntity;
import com.cxyd.modules.wcs.entity.TrkEntity;
import com.cxyd.modules.wcs.service.PostTcpService;
import com.cxyd.modules.wcs.service.TrkService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
import java.util.Map;

@Service
public class TrkServiceImpl extends CrudServiceImpl<TrkDao, TrkEntity, TrkDTO> implements TrkService {
    @Resource
    private PostWmsDao postWmsDao;
    @Resource
    private PostTcpService postTcpService;
    @Resource
    private AgvTrkHkDao agvTrkHkDao;
    @Resource
    private ReceiveTaskDao receiveTaskDao;

    @Override
    public QueryWrapper<TrkEntity> getWrapper(Map<String, Object> params) {
        String trkId = (String) params.get("trkId");
        String contNo = (String) params.get("contNo");
        String trkType = (String) params.get("trkType");
        String trkSt = (String) params.get("trkSt");
        String dvcNo = (String) params.get("dvcNo");
        String frmPos = (String) params.get("frmPos");
        String toPos = (String) params.get("toPos");
        QueryWrapper<TrkEntity> wrapper = new QueryWrapper<>();
        wrapper.eq(StringUtils.isNotBlank(trkId), "trk_id", trkId);
        wrapper.eq(StringUtils.isNotBlank(dvcNo), "dvc_no", dvcNo);
        wrapper.eq(StringUtils.isNotBlank(trkType), "trk_type", trkType);
        wrapper.eq(StringUtils.isNotBlank(frmPos), "frm_pos", frmPos);
        wrapper.eq(StringUtils.isNotBlank(toPos), "to_pos", toPos);
        wrapper.eq(StringUtils.isNotBlank(trkSt), "trk_st", trkSt);
        wrapper.like(StringUtils.isNotBlank(contNo), "cont_no", contNo);
        return wrapper;
    }

    @Override
    public TrkEntity selectByDvcNo(String dvcNo) {
        QueryWrapper<TrkEntity> qw = new QueryWrapper<>();
//        查找目标设备的初始搬送任务
        qw.lambda().eq(TrkEntity::getDvcNo, dvcNo)
                .eq(TrkEntity::getTrkSt, WcsConstants.TRK_STATUS_START)
                .last("limit 1");
        return baseDao.selectOne(qw);
    }

    @Override
    public TrkEntity selectByRequestPk(String requestPk) {
        QueryWrapper<TrkEntity> qw = new QueryWrapper<>();
        qw.lambda().eq(TrkEntity::getRequestPk, requestPk)
                .last("limit 1");
        return baseDao.selectOne(qw);
    }

    @Override
    public TrkEntity selectByContNo(String contNo) {
        QueryWrapper<TrkEntity> qw = new QueryWrapper<>();
        qw.lambda().eq(TrkEntity::getContNo, contNo)
                .last("limit 1");
        return baseDao.selectOne(qw);
    }

    @Override
    public TrkEntity selectByGroupNo(String groupNo) {
        QueryWrapper<TrkEntity> qw = new QueryWrapper<>();
        qw.lambda().eq(TrkEntity::getGroupNo, groupNo)
                .eq(TrkEntity::getDvcNo, "WAIT_AGV")
                .eq(TrkEntity::getTrkSt, WcsConstants.TRK_STATUS_START)
                .last("limit 1");
        return baseDao.selectOne(qw);
    }

    @Override
    public void updateTrkByContNo(String contNo) {
//        1.根据托盘信息处理wcs_trk数据
        QueryWrapper<TrkEntity> qw = new QueryWrapper<>();
        qw.lambda().eq(TrkEntity::getContNo, contNo)
                .eq(TrkEntity::getTrkSt, WcsConstants.TRK_STATUS_DONE);
        TrkEntity trkEntity = baseDao.selectOne(qw);
//        1.更新上报状态
        trkEntity.setFbSt(1);
        trkEntity.setUpdater(WcsConstants.WCS_USER_ID);
        trkEntity.setUpdateDate(new Date());
        baseDao.updateById(trkEntity);
//        2.转移数据至历史表[his_wcs_trk]
        baseDao.backupTrk(contNo);
//        3.删除当前数据
        baseDao.deleteById(trkEntity);
    }

    @Override
    public void updateTrkByGroupNo(String groupNo) {
        if (StringUtils.isBlank(groupNo)) {
            return;
        }
        baseDao.backupTrkByGroupNo(groupNo);
        baseDao.deleteTrkByGroupNo(groupNo);
    }

    @Override
    public ProcResult trkHandler(Map<String, Object> params) {
//        接收任务ID已经操作方式
        String trkId = (String) params.get("trkId");
        String operateType = (String) params.get("operateType");
//        判断任务是否存在(不存在报错)
        TrkEntity trkEntity = baseDao.selectById(trkId);
        if (trkEntity == null) {
            return new ProcResult().result("trkHandler_003", "主任务[" + trkId + "]不存在!");
        }
//        根据操作方式进行数据处理(REPEAT/DONE/CANCEL/DELETE)
        if (WcsConstants.TASK_FORCE_REPEAT_OPERATE.equals(operateType)) {
//          只能重发异常状态的任务
            if (WcsConstants.TRK_STATUS_ERROR != trkEntity.getTrkSt()) {
                return new ProcResult().result("trkHandler_004", "只有[异常]状态下的任务允许重发!");
            }
//          将状态设置为初始
            trkEntity.setTrkSt(WcsConstants.TRK_STATUS_START);
//          备注信息人为操作
            trkEntity.setComments("人工将任务重新下发!");
//          更新时间
            trkEntity.setUpdateDate(new Date());
        } else if (WcsConstants.TASK_FORCE_DONE_OPERATE.equals(operateType)) {
//            判断任务状态是否能够强制完成
            if (WcsConstants.TRK_STATUS_RUNNING == trkEntity.getTrkSt()) {
                return new ProcResult().result("trkHandler_006", "当前任务正在执行中!如果人为已将料架送至目标位置,请先取消任务后再强制完成!");
            }

        } else if (WcsConstants.TASK_MANUAL_CANCEL_OPERATE.equals(operateType)) {
//            判断任务状态是否能够取消
//            将状态设置为取消
            trkCancelHandler(trkEntity);
        } else if (WcsConstants.TASK_MANUAL_DELETE_OPERATE.equals(operateType)) {
            if (WcsConstants.TRK_STATUS_CANCEL != trkEntity.getTrkSt()) {
                return new ProcResult().result("trkHandler_007", "只有[已取消]状态下的任务允许删除!");
            }
            trkDeleteHandler(trkEntity);
        } else {
            return new ProcResult().result("trkHandler_005", "作业类型不存在!");
        }
        baseDao.updateById(trkEntity);
        return new ProcResult().result("0", "success");
    }

    private void trkDoneHandler(TrkEntity wcsTrk) {
//            将状态设置为完成
        wcsTrk.setTrkSt(WcsConstants.TRK_STATUS_DONE);
        wcsTrk.setComments("人工将任务强制完成!");
        wcsTrk.setUpdateDate(new Date());
//      任务接收后上报wms系统[wcs_post_wms]（只有MES下发的任务需要上报）
        if (WcsConstants.MES_USER_ID == wcsTrk.getCreator()) {
            PostWmsEntity postWms = new PostWmsEntity();
            postWms.setRequestPk(wcsTrk.getRequestPk());
            postWms.setContNo(wcsTrk.getContNo());
            postWms.setCurPos(wcsTrk.getToPos());
//        类型为[完成]
            postWms.setNoticeType(WcsConstants.POST_TYPE_DONE);
            postWms.setCode("0");
            postWms.setResult("人工将任务强制完成!");
            postWms.setPostSt(WcsConstants.POST_STATUS_START);
            postWms.setCreator(WcsConstants.WCS_USER_ID);
            postWms.setUpdateDate(new Date());
            postWmsDao.insert(postWms);
        }
    }

    private void trkCancelHandler(TrkEntity wcsTrk) {
//            将状态设置为取消
        wcsTrk.setTrkSt(WcsConstants.TRK_STATUS_CANCEL);
        wcsTrk.setComments("人工将任务取消!");
        wcsTrk.setUpdateDate(new Date());
//        判断AGV任务是否存在
        QueryWrapper<AgvTrkHkEntity> agvQw = new QueryWrapper<>();
        agvQw.lambda().eq(AgvTrkHkEntity::getTrkId, wcsTrk.getTrkId()).last("limit 1");
        AgvTrkHkEntity agvTrkHkEntity = agvTrkHkDao.selectOne(agvQw);
        if (agvTrkHkEntity != null) {
//            尝试取消对应的post—tcp信息
            postTcpService.backupPostTcpByTaskCode(agvTrkHkEntity.getTaskCode());
            agvTrkHkEntity.setStatus(RcsConstants.AGV_TRK_HK_CANCEL);
            agvTrkHkEntity.setData("人工取消任务!");
            agvTrkHkEntity.setUpdateDate(new Date());
            agvTrkHkDao.updateById(agvTrkHkEntity);
        }
//        取消任务（前置任务属于内部任务直接取消，后置任务需要同步取消MES）
        baseDao.updateById(wcsTrk);
        if (WcsConstants.MES_USER_ID.equals(wcsTrk.getCreator())) {
//            匹配任务并取消任务信息
            QueryWrapper<ReceiveTaskEntity> rqw = new QueryWrapper<>();
            rqw.lambda().eq(ReceiveTaskEntity::getRequestPk, wcsTrk.getRequestPk()).last("limit 1");
            ReceiveTaskEntity receiveTaskEntity = receiveTaskDao.selectOne(rqw);
            if (receiveTaskEntity != null) {
                receiveTaskEntity.setStatus(WcsConstants.RECEIVE_TASK_CANCEL);
                receiveTaskEntity.setComments("人工取消MES后置任务!");
                receiveTaskEntity.setUpdateDate(new Date());
                receiveTaskDao.updateById(receiveTaskEntity);
            }
        } else {
//            内部的前置任务取消,同时判断一下是否有后置任务,如果有则一并取消
            QueryWrapper<TrkEntity> bqw = new QueryWrapper<>();
            bqw.lambda().eq(TrkEntity::getGroupNo, wcsTrk.getGroupNo())
                    .lt(TrkEntity::getTrkSt, WcsConstants.TRK_STATUS_CANCEL);
            List<TrkEntity> bTrkList = baseDao.selectList(bqw);
            if (bTrkList != null && bTrkList.size() > 0) {
                for (TrkEntity bTrk : bTrkList) {
                    bTrk.setTrkSt(WcsConstants.TRK_STATUS_CANCEL);
                    bTrk.setComments("人工取消前置任务!");
                    bTrk.setUpdateDate(new Date());
                    baseDao.updateById(bTrk);
                    // 匹配搬送指令并取消
                    QueryWrapper<ReceiveTaskEntity> gqw = new QueryWrapper<>();
                    gqw.lambda().eq(ReceiveTaskEntity::getRequestPk, bTrk.getRequestPk()).last("limit 1");
                    ReceiveTaskEntity groupTask = receiveTaskDao.selectOne(gqw);
                    if (groupTask != null) {
                        groupTask.setStatus(WcsConstants.RECEIVE_TASK_CANCEL);
                        groupTask.setComments("人工取消前置任务时,后置任务一并取消!");
                        groupTask.setUpdateDate(new Date());
                        receiveTaskDao.updateById(groupTask);
                    }
                }
            }
        }
        //    取消任务成功后-对应预分配信息也需要一并释放掉
    }

    private void trkDeleteHandler(TrkEntity wcsTrk) {
//        删除AGV搬送任务(判断是否有任务可以删除)
        QueryWrapper<AgvTrkHkEntity> agvQw = new QueryWrapper<>();
        agvQw.lambda().eq(AgvTrkHkEntity::getTrkId, wcsTrk.getTrkId())
                .eq(AgvTrkHkEntity::getStatus, RcsConstants.AGV_TRK_HK_CANCEL).last("limit 1");
        AgvTrkHkEntity agvTrkHkEntity = agvTrkHkDao.selectOne(agvQw);
        if (agvTrkHkEntity != null) {
            agvTrkHkDao.deleteById(agvTrkHkEntity);
        }
//        删除wcs_trk数据
        baseDao.deleteById(wcsTrk);
//        删除receive_task数据
        if (WcsConstants.MES_USER_ID.equals(wcsTrk.getCreator())) {
//            匹配任务并取消任务信息
            QueryWrapper<ReceiveTaskEntity> rqw = new QueryWrapper<>();
            rqw.lambda().eq(ReceiveTaskEntity::getRequestPk, wcsTrk.getRequestPk()).last("limit 1");
            ReceiveTaskEntity receiveTaskEntity = receiveTaskDao.selectOne(rqw);
            if (receiveTaskEntity != null) {
                receiveTaskDao.deleteById(receiveTaskEntity);
            }
        } else {
            QueryWrapper<TrkEntity> dqw = new QueryWrapper<>();
            dqw.lambda().eq(TrkEntity::getGroupNo, wcsTrk.getGroupNo())
                    .eq(TrkEntity::getTrkSt, WcsConstants.TRK_STATUS_CANCEL);
            List<TrkEntity> dTrkList = baseDao.selectList(dqw);
            if (dTrkList != null && dTrkList.size() > 0) {
                for (TrkEntity dTrk : dTrkList) {
                    QueryWrapper<ReceiveTaskEntity> gqw = new QueryWrapper<>();
                    gqw.lambda().eq(ReceiveTaskEntity::getRequestPk, dTrk.getRequestPk()).last("limit 1");
                    ReceiveTaskEntity groupTask = receiveTaskDao.selectOne(gqw);
                    if (groupTask != null) {
                        receiveTaskDao.deleteById(groupTask);
                    }
                    baseDao.deleteById(dTrk);
                }
            }

        }
    }
}
